/**
 * Copyright 2010 Victor Egea Hernando
 *
 * RockScript is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 * 
 * RockScript is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with RockScript.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef ROCKPARSER_H_
#define ROCKPARSER_H_

#include "lexer.h"

#include <paper/paper.h>
#include <corelib/types.h>

namespace rock{

// parser flags
enum flags{
    FLG_LOOP = 1,
    FLG_SWITCH = 2,
    FLG_STATIC = 4,
    FLG_OPERATOR = 8,
    FLG_CONSTRUCTOR = 16,
    FLG_COMPILER_ERROR = 32
};

/**
 * @brief Rock language token with extra information
 * @author Victor Egea Hernando
 * @date 15/11/2009
 */
typedef struct{
    //! @brief Line and column where token is placed
    corelib::uint32 line_;
    //! @brief token
    token tk_;
} token_extra_inf;

/**
 * @brief A handler that reads an error from the lexer,
 * it's usually used by the sintactic parser
 * @author Victor Egea Hernando
 * @date 15/11/2009
 */
class parser_error_hnd {

public:
    /**
     * @brief
     */
    virtual void parserError( corelib::uint32 line, const corelib::ustring &error ) = 0;

};

// A handler that gets chars from a file
class gc_ffile_hnd;
// A handler that gets chars from a buffer
class gc_fbuffer_hnd;

/**
 * @brief Parses rock tokens in the Recursive Descent (RD) hand-writing fashion.
 * @author Victor Egea Hernando
 * @date 17/11/2009
 */
class parser : public lexer_error_hnd
{

public:
    /*------------------------------------------------------------------
       constructrs & destructor
      ------------------------------------------------------------------*/
    //
    parser( void );
    //
    virtual ~parser();

    /*------------------------------------------------------------------
       main interface
      ------------------------------------------------------------------*/
    //
    void parseFStream( get_char_hnd &hnd );
    //
    void parseFBuffer( const char *script, corelib::uint32 size );
    //
    void parseFFile( bool &is_open, const char *path );
    //
    void setErrorHnd( parser_error_hnd &hnd );
    //
    bool error( void ) const;
    //
    void setVMachine( paper::vmachine &vm );
    //
    static corelib::ustring unmangleMNames( const corelib::ustring &mstr );

protected:
    /*------------------------------------------------------------------
       internal interface
      ------------------------------------------------------------------*/
    // reset
    void reset( void );
    // compile
    void parse( void );
    // feed the lexer from a file
    void feedFromFile( const char *path );
    // feed lexxer from a buffer
    void feedFromBuffer( const char *buffer, corelib::uint32 size );

    /*------------------------------------------------------------------
       error manipulation
      ------------------------------------------------------------------*/

    // throw unexpected token error
    void unexpectedTkErr( void );
    // throw expected token error
    void expectedTkErr( corelib::uint32 type );
    // process lexer errors
    virtual void lexError( corelib::uint32 line, const corelib::ustring &error );

    /*------------------------------------------------------------------
       recursive descent parser
      ------------------------------------------------------------------*/

    // rock main block
    void main_block( void );
    // import statement
    void import_stm( void );
    // class definion
    void class_def( void );
    // var declaration
    void var_dec( void );
    // constructor definition
    void cnstr_def( void );
    // operator def
    void operator_def( void );
    // method definition
    void method_def( void );
    // block body
    void block_body( void );
    // do while loop
    void dowhile_loop( void );
    // while loop
    void while_loop( void );
    // foreach loop
    void foreach_loop( void );
    // switch jumps
    void switch_jumps( void );
    // try-catch block
    void try_catch_block( void );
    // if-else blocks
    void if_else_blocks( void );
    // variable definition
    void var_def( void );
    // gets the arguments fro a call
    corelib::uint32 call_arguments( void );
    // instance method calls
    void method_calls( corelib::uint32 pre_op );
    // var expression
    bool var_expression( void );
    // expression
    bool expression( void );
    // expression branch
    bool exp_branch( void );
    // logical expression
    bool exp_logical( void );
    // or, xor & and expression
    bool exp_or_xor_and( void );
    // equality expression
    bool exp_equality( void );
    // relational expression
    bool exp_relational( void );
    // shift expression
    bool exp_shift( void );
    // in & instanceof expression
    bool exp_in_instof( void );
    // simple expression
    bool exp_simple( void );
    // term
    bool term( void );
    // factor
    bool factor( void );
    // language object
    bool language_obj( corelib::uint32 pre_op );
    // object instance
    bool obj_instance( void );
    // class instance
    void class_instance( void );
    // post operation
    bool post_op( corelib::uint32 pre_op );

    /*------------------------------------------------------------------
       types
      ------------------------------------------------------------------*/
    // argument hash
    typedef corelib::hash_map<corelib::ustring, corelib::int16, 
        corelib::ustring_hash> argument_t;

    /*------------------------------------------------------------------
       parsing attributes
      ------------------------------------------------------------------*/
    // the handler gets chars from a buffer
    gc_fbuffer_hnd *gcFBufferHnd_;
    // rock parser error handler
    parser_error_hnd *errorHnd_;
    // the handler gets chars from a file
    gc_ffile_hnd *gcFFileHnd_;
    // current token
    token_extra_inf ctk_;
    // rock language lexer
    lexer lexer_;

    /*------------------------------------------------------------------
       compiling attributes
      ------------------------------------------------------------------*/
    // argument hash
    argument_t args_;
    // current namespace
    corelib::ustring cns_;
    // current method name
    corelib::ustring mname_;
    // current package name
    corelib::ustring pname_;
    // virtual machine pointer
    paper::vmachine *vm_;
    // active class
    paper::vm_class* ac_;
    // active method
    paper::method* am_;
    // number of expression registers & local variables
    corelib::uint32 neregs_, nlvars_;

    /*------------------------------------------------------------------
       miscelaneous attributes
      ------------------------------------------------------------------*/
    // parser flags
    corelib::uint32 flags_;
    // current register position & expression position
    corelib::int16 cregp_, expp_;

};

}; // namespace rock

#endif // ROCKPARSER_H_
